package com.mframe.web.controller.activiti;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mframe.common.base.AjaxResult;
import com.mframe.framework.web.page.PageDomain;
import com.mframe.framework.web.page.TableDataInfo;
import com.mframe.framework.web.page.TableSupport;
import com.mframe.web.core.base.BaseController;

/**
 * Created by Administrator on 2018/8/31.
 */
@Controller
@RequestMapping("/activiti")
public class ModelerController extends BaseController{

	private String prefix = "activiti";
	
    @Autowired
    RepositoryService repositoryService;
    
    @Autowired
    private ObjectMapper objectMapper;

    @RequiresPermissions("activiti:model")
	@GetMapping("/model")
	public String model() {
		return prefix + "/activiti";
	}
    
    
	@PostMapping("/list")
	@ResponseBody
	public TableDataInfo list() {
		PageDomain pageDomain = TableSupport.buildPageRequest();
		ModelQuery modelQuery=repositoryService.createModelQuery();
		List<Model> list =new ArrayList<Model>();
		Integer pageNum = pageDomain.getPageNum();
        Integer pageSize = pageDomain.getPageSize();
		list = modelQuery.orderByCreateTime().desc().listPage((pageNum-1)*pageSize, pageSize); 
		TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(0);
        rspData.setRows(list);
        rspData.setTotal(modelQuery.count());
		return rspData;
	}
    
	@GetMapping("/add")
	public String add(ModelMap mmap) {
		return prefix + "/add";
	}
	
    @GetMapping(value = "/create")
    public String createFlow(String name,String key,String description) throws UnsupportedEncodingException{
        //初始化一个空模型
        Model model = repositoryService.newModel();
        //设置一些默认信息
        int revision = 1;
        description = StringUtils.defaultString(description);
        ObjectNode modelNode = objectMapper.createObjectNode();
        modelNode.put(ModelDataJsonConstants.MODEL_NAME,name);
        modelNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description);
        modelNode.put(ModelDataJsonConstants.MODEL_REVISION, revision);
        model.setName(name);
        model.setKey(key);
        model.setMetaInfo(modelNode.toString());
        repositoryService.saveModel(model);
        String id = model.getId();

        //完善ModelEditorSource
        ObjectNode editorNode = objectMapper.createObjectNode();
        editorNode.put("id", "canvas");
        editorNode.put("resourceId", "canvas");
        ObjectNode stencilSetNode = objectMapper.createObjectNode();
        stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#");
        editorNode.put("stencilset", stencilSetNode);
        repositoryService.addModelEditorSource(id,editorNode.toString().getBytes("utf-8"));
        return "redirect:/editor?modelId="+id;
    }

  
    /**
     * 编辑模型
     */
	@RequestMapping(value = "edit")
    public String edit(String modelId) {
		return "redirect:/editor?modelId="+modelId;
	}
	
	/**
	 * 删除模型
	 * @param modelId
	 * @return
	 */
	@PostMapping("/remove")
	@ResponseBody
	public AjaxResult remove(String modelId) {
		try {
			repositoryService.deleteModel(modelId);
			return toAjax(1);
		} catch (Exception e) {
			return error(e.getMessage());
		}
	}
	
	
    @ResponseBody
    @GetMapping(value = "/flowList")
    public List<Model> listFlow(){
        List<Model> flowList = repositoryService.createModelQuery().list();
        return flowList;
    }

/*    @ResponseBody
    @GetMapping(value = "/deployList")
    public List<DeploymentResponse> deployList(){
        List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
        for (Deployment deployment : deployments){
            deployList.add(new DeploymentResponse(deployment));
        }
        return deployList;
    }*/


    @ResponseBody
    @GetMapping(value = "/flowDelete")
    public void flowDelete(@RequestParam(name = "id") String id){
        System.out.println("id = "+id);
        repositoryService.deleteModel(id);
    }

    @ResponseBody
    @PostMapping(value = "/deploy")
    public AjaxResult deploy(@RequestParam(name = "id") String id) throws Exception{
        //获取模型
        Model modelData = repositoryService.getModel(id);
        byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
        if (null == bytes){
            return  AjaxResult.error("模型数据为空，请先设计流程并成功保存，再进行发布。");
        }
        JsonNode modelNode = new ObjectMapper().readTree(bytes);
        BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode);
        if (model.getProcesses().size() == 0){
            return AjaxResult.error("数据模型不符合要求，请至少设计一条主线程流。");
        }
        byte[] bpmnBytes = new BpmnXMLConverter().convertToXML(model);

        //发布流程
        String processName = modelData.getName() + ".bpmn20.xml";
        Deployment deployment = repositoryService.createDeployment()
                .name(modelData.getName())
                .addString(processName, new String(bpmnBytes, "UTF-8"))
                .deploy();
        modelData.setDeploymentId(deployment.getId());
        repositoryService.saveModel(modelData);
        
        return AjaxResult.success("部署成功");
    }


    @ResponseBody
    @GetMapping(value = "/deleteDeploy")
    public void deleteDeploy(@RequestParam(name = "id") String id){
        repositoryService.deleteDeployment(id);
    }
}
